package com.gitee.wsl.ext.string


/**
 * 返回字符串 searchStr 在字符串 str 中第 ordinal 次出现的位置。
 *
 *
 *
 * 如果 str=null 或 searchStr=null 或 ordinal0 则返回-1<br></br>
 * 此方法来自：Apache-Commons-Lang
 *
 *
 * 例子（*代表任意字符）：
 *
 * <pre>
 * CharSequenceUtil.ordinalIndexOf(null, *, *)          = -1
 * CharSequenceUtil.ordinalIndexOf(*, null, *)          = -1
 * CharSequenceUtil.ordinalIndexOf("", "", *)           = 0
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "a", 1)  = 0
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "a", 2)  = 1
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "b", 1)  = 2
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "b", 2)  = 5
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "", 1)   = 0
 * CharSequenceUtil.ordinalIndexOf("aabaabaa", "", 2)   = 0
</pre> *
 *
 * @param str       被检查的字符串，可以为null
 * @param searchStr 被查找的字符串，可以为null
 * @param ordinal   第几次出现的位置
 * @return 查找到的位置
 * @since 3.2.3
 */
fun CharSequence.ordinalIndexOf(searchStr: CharSequence, ordinal: Int): Int {
    if (ordinal <= 0) {
        return -1
    }
    if (searchStr.isEmpty()) {
        return 0
    }

    var found = 0
    var index: Int = -1
    do {
        index = indexOf( searchStr, index + 1, lastIndex,ignoreCase=false)
        if (index < 0) {
            return index
        }
        found++
    } while (found < ordinal)
    return index
}

fun CharSequence.indexOf(other: CharSequence, startIndex: Int, endIndex: Int, ignoreCase: Boolean, last: Boolean = false): Int {
    val indices = if (!last)
        startIndex.coerceAtLeast(0)..endIndex.coerceAtMost(length)
    else
        startIndex.coerceAtMost(lastIndex) downTo endIndex.coerceAtLeast(0)

    if (this is String && other is String) { // smart cast
        for (index in indices) {
            if (other.regionMatches(0, this, index, other.length, ignoreCase))
                return index
        }
    } else {
        for (index in indices) {
            if (other.regionMatchesImpl(0, this, index, other.length, ignoreCase))
                return index
        }
    }
    return -1
}

/**
 * Implementation of [regionMatches] for CharSequences.
 * Invoked when it's already known that arguments are not Strings, so that no additional type checks are performed.
 */
internal fun CharSequence.regionMatchesImpl(thisOffset: Int, other: CharSequence, otherOffset: Int, length: Int, ignoreCase: Boolean): Boolean {
    if ((otherOffset < 0) || (thisOffset < 0) || (thisOffset > this.length - length) || (otherOffset > other.length - length)) {
        return false
    }

    for (index in 0 until length) {
        if (!this[thisOffset + index].equals(other[otherOffset + index], ignoreCase))
            return false
    }
    return true
}